﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace engine
{
    public class DataMatcher
    {
        #region 基础
        private NodeBase _textRangeNode;
        private List<Unit> _units;

        public bool ShouldThrowError { get; set; }
        public List<string> ErrorMessages { get; set; }

        public DataMatcher(NodeBase textRangeNode, List<Unit> units)
        {
            ShouldThrowError = true;
            if(textRangeNode == null)
            {
                throw new Exception("匹配节点不能为null");
            }
            _textRangeNode = textRangeNode;
            _units = units;

            ErrorMessages = new List<string>();
        }

        private void Error(string message = null)
        {
            if (ShouldThrowError)
            {
                throw new Exception(message);
            }
            else
            {
                ErrorMessages.Add(message);
            }
        }
        #endregion

        #region token相关
        private int beginChildIndex = 0;
        private int beginChildTextIndex = 0;
        private int endChildIndex = 0;
        private int endChildTextIndex = 0;

        private MatchToken GetToken()
        {
            MatchToken token = new MatchToken();
            if (endChildIndex >= _units.Count)
            {
                Error("索引超出范围");
            }
            Unit unit = _units[endChildIndex];
            if (unit is PictureUnit)
            {
                token.PictureUnit = unit as PictureUnit;
            }
            else
            {
                TextRangeUnit temp = unit as TextRangeUnit;
                TextRangeUnit textRangeUnit = new TextRangeUnit();
                textRangeUnit.Source = temp.Source;
                textRangeUnit.CharactorFormat = temp.CharactorFormat;
                textRangeUnit.Text = temp.Text[endChildTextIndex].ToString();
                token.TextRangeUnit = textRangeUnit;
            }
            return token;
        }

        private bool HasNextToken()
        {
            // 继续判断是否有下一个元素
            if (beginChildIndex + 1 < _units.Count)
            {
                return true;
            }
            // 如果不存在下一个元素了，判断当前元素
            if (beginChildIndex < _units.Count)
            {
                // 说明没有超出范围
                Unit unit = _units[beginChildIndex];
                if (unit is TextRangeUnit)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                    // 是否有下一个字符
                    if (beginChildTextIndex + 1 < textRangeUnit.Text.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void MoveToNextToken()
        {
            // 当前元素
            if (beginChildIndex < _units.Count)
            {
                // 说明没有超出范围
                Unit unit = _units[beginChildIndex];
                if (unit is TextRangeUnit)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                    // 是否有下一个字符
                    if (beginChildTextIndex + 1 < textRangeUnit.Text.Length)
                    {
                        beginChildTextIndex++;
                        endChildTextIndex = beginChildTextIndex;
                        return;
                    }
                }
            }
            // 下一个元素
            beginChildTextIndex = 0;
            endChildTextIndex = 0;
            while (true)
            {
                beginChildIndex++;
                endChildIndex = beginChildIndex;
                if (beginChildIndex < _units.Count)
                {
                    // 说明没有超出范围
                    Unit unit = _units[beginChildIndex];
                    if (unit is TextRangeUnit)
                    {
                        // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                        TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                        if (textRangeUnit.Text.Length > 0)
                        {
                            return;
                        }
                    }
                    else if (unit is PictureUnit)
                    {
                        return;
                    }
                    else
                    {
                        Error("节点类型错误");
                    }
                }
                else
                {
                    Error("不存在token");
                }
            }
        }

        private bool HasNextMarkerToken()
        {
            // 判断是否有下一个元素
            if (endChildIndex + 1 < _units.Count)
            {
                return true;
                //NodeBase nodeBase = _paragraphNode.Children[endChildIndex + 1];
                //if(nodeBase is TextRangeNode)
                //{
                //    return true;
                //}
            }
            // 如果不存在下一个元素了，判断当前元素
            if (endChildIndex < _units.Count)
            {
                // 说明没有超出范围
                Unit unit = _units[endChildIndex];
                if (unit is TextRangeUnit)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                    // 是否有下一个字符
                    if (endChildTextIndex + 1 < textRangeUnit.Text.Length)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void MoveToNextMarkerToken()
        {
            if(endChildTextIndex == -1)
            {
                // 说明溢出处理过
                endChildTextIndex = 0;
                return;
            }
            // 当前元素
            if (endChildIndex < _units.Count)
            {
                // 说明没有超出范围
                Unit unit = _units[endChildIndex];
                if (unit is TextRangeUnit)
                {
                    // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                    TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                    // 是否有下一个字符
                    if (endChildTextIndex + 1 < textRangeUnit.Text.Length)
                    {
                        endChildTextIndex++;
                        return;
                    }
                }
            }
            // 下一个元素
            endChildTextIndex = 0;
            while (true)
            {
                endChildIndex++;
                if (endChildIndex < _units.Count)
                {
                    // 说明没有超出范围
                    Unit nodeBase = _units[endChildIndex];
                    if (nodeBase is TextRangeUnit)
                    {
                        // 必须是textrange类型的节点才可以解析,判断后面还有没有字符
                        TextRangeUnit textRangeUnit = nodeBase as TextRangeUnit;
                        if (textRangeUnit.Text.Length > 0)
                        {
                            return;
                        }
                    }
                    else if (nodeBase is PictureUnit)
                    {
                        return;
                    }
                    else
                    {
                        Error("节点类型错误");
                    }
                }
                else
                {
                    Error("不存在token");
                }
            }
        }

        private void MoveToPrevMarkerToken()
        {
            if (endChildTextIndex > 0)
            {
                endChildTextIndex--;
            }
            else if (endChildIndex > 0)
            {
                endChildIndex--;
                Unit unit = _units[endChildIndex];
                if (unit is TextRangeUnit)
                {
                    TextRangeUnit textRangeUnit = unit as TextRangeUnit;
                    endChildTextIndex = textRangeUnit.Text.Length - 1;
                }
            }
            else
            {
                Error("无法移动到前一个token");
            }
        }
        #endregion

        #region match相关
        public object Match()
        {
            // 得到头和尾的普通字符
            List<Unit> head = new List<Unit>();
            List<Unit> tail = new List<Unit>();
            var prev = _textRangeNode.Prev;
            while (prev != null && head.Count < 100)
            {
                if(prev.MappedUnitType == UnitType.TextRange && prev.FuncNode == null)
                {
                    TextRangeNode temp = prev as TextRangeNode;
                    foreach(var c in temp.Text)
                    {
                        head.Add(new TextRangeUnit
                        {
                            Text = c.ToString(),
                            CharactorFormat = temp.CharactorFormat
                        });
                    }
                    prev = prev.Prev;
                }
                else if(prev.MappedUnitType == UnitType.Picture && prev.FuncNode == null)
                {
                    PictureNode temp = prev as PictureNode;
                    head.Add(new PictureUnit
                    {
                        Image = temp.Image
                    });
                    prev = prev.Prev;
                }
                else
                {
                    break;
                }
            }
            var next = _textRangeNode.Next;
            while (next != null && tail.Count < 100)
            {
                if (next.MappedUnitType == UnitType.TextRange && next.FuncNode == null)
                {
                    TextRangeNode temp = next as TextRangeNode;
                    foreach (var c in temp.Text)
                    {
                        tail.Add(new TextRangeUnit
                        {
                            Text = c.ToString(),
                            CharactorFormat = temp.CharactorFormat
                        });
                    }
                    next = next.Next;
                }
                else if (next.MappedUnitType == UnitType.Picture && next.FuncNode == null)
                {
                    PictureNode temp = next as PictureNode;
                    tail.Add(new PictureUnit
                    {
                        Image = temp.Image
                    });
                    next = next.Next;
                }
                else
                {
                    break;
                }
            }

            // 从units中匹配头尾的普通字符，中间夹着的就是匹配到的值
            MatchMarker1(head, false);
            int beginIndex = beginChildIndex;
            int beginTextIndex = beginChildTextIndex;
            MatchMarker1(tail, true);
            int endIndex = beginChildIndex;
            int endTextIndex = beginChildTextIndex;

            if(beginIndex == endIndex && beginTextIndex == endTextIndex)
            {
                return null;
            }
            else
            {
                // 将指针移动到区间的开头部位
                beginChildIndex = beginIndex;
                beginChildTextIndex = beginTextIndex;
                endChildIndex = beginChildIndex;
                endChildTextIndex = beginChildTextIndex;

                object result = null;
                if(_textRangeNode.FuncNode.Config.UnitType == UnitType.Picture)
                {
                    while (true)
                    {
                        if (endChildIndex < endIndex)
                        {
                            MoveToNextMarkerToken();
                        }
                        else if (endChildTextIndex < endTextIndex)
                        {
                            MoveToNextMarkerToken();
                        }
                        else
                        {
                            break;
                        }

                        MatchToken token = GetToken();
                        if (token.IsPicture)
                        {
                            result = token.PictureUnit;
                            break;
                        }
                    }
                }
                else
                {
                    // 匹配到的值需要合并在一起
                    FullString fullString = new FullString();
                    while (true)
                    {
                        if (endChildIndex < endIndex - 1)
                        {
                            MoveToNextMarkerToken();
                        }
                        else if (endChildIndex < endIndex && endTextIndex > 0)
                        {
                            MoveToNextMarkerToken();
                        }
                        else if (endChildTextIndex < endTextIndex - 1)
                        {
                            MoveToNextMarkerToken();
                        }
                        else
                        {
                            break;
                        }
                        Appender(fullString.Items, GetToken());
                    }
                    result = fullString;
                }
                
                // 匹配过的节点需要标记为已匹配
                SetMatched(endIndex);

                return result;
            }
        }

        /// <summary>
        /// 匹配过的节点需要标记为已匹配
        /// </summary>
        private void SetMatched(int endIndex)
        {
            var current = _units[endIndex];
            var prev = current.Prev;
            while(prev != null)
            {
                prev.MatchStatus = MatchStatus.Matched;
                prev = prev.Prev;
            }
            
        }

        private void Appender(List<Unit> children, MatchToken token)
        {
            if(!token.IsPicture && children.Count > 0 && children.Last() is TextRangeUnit)
            {
                TextRangeUnit last = children.Last() as TextRangeUnit;
                if(last.CharactorFormat == token.TextRangeUnit.CharactorFormat)
                {
                    last.Text += token.TextRangeUnit.Text;
                    return;
                }
            }

            children.Add(token.Value);
        }

        /// <summary>
        /// 匹配前后缀
        /// </summary>
        /// <param name="texts"></param>
        /// <param name="isNext"></param>
        private void MatchMarker1(List<Unit> texts, bool isNext = true)
        {
            // 首先得到第一个需要匹配的字符
            Unit firstMatch = null;
            if (isNext)
            {
                firstMatch = texts.FirstOrDefault();
                if(firstMatch == null)
                {
                    // 说明不存在后缀，则需要移动到末尾再往后一个字符
                    while (HasNextMarkerToken())
                    {
                        MoveToNextMarkerToken();
                    }
                    endChildTextIndex += 1;
                    beginChildIndex = endChildIndex;
                    beginChildTextIndex = endChildTextIndex;
                    return;
                }
            }
            else
            {
                firstMatch = texts.LastOrDefault();
                if(firstMatch == null)
                {
                    // 说明不存在前缀，再往前移动一个字符。不能修改endChildTextIndex，因为会影响后续对tail的操作
                    //endChildTextIndex -= 1;
                    beginChildTextIndex -= 1;
                    //beginChildTextIndex = endChildTextIndex;
                    return;
                }
            }

            while (true)
            {
                MatchToken token = GetToken();
                if (token.DoMatch(firstMatch))
                {
                    if (MatchMarker2(texts, isNext))
                    {
                        break;
                    }
                }

                if (HasNextToken())
                {
                    MoveToNextToken();
                }
                else
                {
                    break;
                }
            }

        }

        /// <summary>
        /// 对比文本是否与前后缀一致
        /// </summary>
        /// <param name="texts"></param>
        /// <param name="isNext"></param>
        /// <returns></returns>
        private bool MatchMarker2(List<Unit> texts, bool isNext = true)
        {
            //if (texts.Count == 0)
            //{
            //    if (isNext)
            //    {
            //        // 如果尾部没有标记，则移动到最后一个字符
            //        beginChildIndex = _units.Count == 0 ? 0 : _units.Count - 1;
            //        endChildIndex = beginChildIndex;
            //        var last = _units[endChildTextIndex] as TextRangeUnit;
            //        if (last != null)
            //        {
            //            beginChildTextIndex = last.Text.Length == 0 ? 0 : last.Text.Length - 1;
            //            endChildTextIndex = beginChildTextIndex;
            //        }
            //    }
            //    return true;
            //}

            if (isNext)
            {
                for (int i = 0; i < texts.Count; i++)
                {
                    MatchToken token = GetToken();
                    if (token.DoMatch(texts[i]))
                    {
                        if(i < texts.Count - 1)
                        {
                            MoveToNextMarkerToken();
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            else
            {
                for (int i = texts.Count - 1; i >= 0; i--)
                {
                    MatchToken token = GetToken();
                    if (token.DoMatch(texts[i]))
                    {
                        if(i > 0)
                        {
                            MoveToPrevMarkerToken();
                        }
                    }
                    else
                    {
                        return false;
                    }
                }
            }
            return true;
        }
        #endregion
        
        public class MatchToken
        {
            public bool IsPicture
            {
                get
                {
                    return PictureUnit != null;
                }
            }

            public Unit Value
            {
                get
                {
                    if (IsPicture)
                    {
                        return PictureUnit;
                    }
                    else
                    {
                        return TextRangeUnit;
                    }
                }
            }

            public PictureUnit PictureUnit { get; set; }
            public TextRangeUnit TextRangeUnit { get; set; }

            public bool DoMatch(Unit unit)
            {
                if(!IsPicture && unit.UnitType == UnitType.TextRange && TextRangeUnit.Text == (unit as TextRangeUnit).Text)
                {
                    return true;
                }
                else if(IsPicture && unit.UnitType == UnitType.Picture && 
                    PictureUnit.Image.Width == (unit as PictureUnit).Image.Width &&
                    PictureUnit.Image.Height == (unit as PictureUnit).Image.Height)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
        }
    }
}
